/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.hjq.permissions;

import ohos.aafwk.ability.Ability;
import ohos.bundle.IBundleManager;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 权限处理module
 */
public class PermissionModule {
    private static Map<Integer, Boolean> sRequestCodes = new HashMap<>();
    /**
     * 权限回调对象
     */
    private OnPermission mCallBack;

    private int mRequestCode;

    public PermissionModule(OnPermission callBack) {
        this.mCallBack = callBack;
    }

    /**
     * 申请权限
     *
     * @param ability ability
     * @param xxPermissions xxPermissions
     * @param permissions permissions
     */
    public void beginRequest(Ability ability, XXPermissions xxPermissions, ArrayList<String> permissions) {
        if (permissions == null || permissions.size() == 0) {
            throw new PermissionException("request permission is empty");
        }
        if (mCallBack == null) {
            throw new PermissionException("permission callBack is null");
        }
        if (ability == null || ability.isTerminating()) {
            mCallBack.noPermission(permissions, false);
            return;
        }
        // 请求码随机生成，避免随机产生之前的请求码，必须进行循环判断
        do {
            mRequestCode = PermissionUtils.getRandomRequestCode();
        } while (sRequestCodes.get(mRequestCode) != null && sRequestCodes.get(mRequestCode));
        sRequestCodes.put(mRequestCode, true);
        List<String> haveList = new ArrayList<>();
        List<String> noNeedPointReqList = new ArrayList<>();
        List<String> needReqList = new ArrayList<>();
        for (String permission : permissions) {
            if (ability.verifySelfPermission(permission) != IBundleManager.PERMISSION_GRANTED) {
                if (ability.canRequestPermission(permission)) {
                    needReqList.add(permission);
                } else {
                    noNeedPointReqList.add(permission);
                }
            } else {
                haveList.add(permission);
            }
        }

        if (needReqList.size() == 0 && xxPermissions != null) {
            // 移除ability的监听
            xxPermissions.removeLiftCycleObserver();
        }
        if (haveList.size() > 0) {
            mCallBack.hasPermission(needReqList, needReqList.size() == 0);
        }
        if (noNeedPointReqList.size() > 0) {
            mCallBack.noPermission(noNeedPointReqList, true);
        }
        if (needReqList.size() > 0) {
            String[] strings = new String[needReqList.size()];
            needReqList.toArray(strings);
            ability.requestPermissionsFromUser(strings, mRequestCode);
        }
    }

    /**
     * 增加 权限结果监听
     *
     * @param ability ability
     * @param requestCode requestCode
     * @param permissions permissions
     * @param grantResults grantResults
     */
    public void addPermissionsForResult(Ability ability, int requestCode, String[] permissions, int[] grantResults) {
        if (mRequestCode != requestCode) {
            return;
        }
        // 释放对这个请求码的占用
        sRequestCodes.remove(requestCode);
        // 获取已授予的权限
        List<String> grantedPermission = PermissionUtils.getGrantedPermission(permissions, grantResults);

        // 如果请求成功的权限集合大小和请求的数组一样大时证明权限已经全部授予
        if (grantedPermission.size() == permissions.length) {
            // 代表申请的所有的权限都授予了
            mCallBack.hasPermission(grantedPermission, true);
            return;
        }

        // 获取被拒绝的权限
        List<String> deniedPermission = PermissionUtils.getDeniedPermission(permissions, grantResults);

        // 代表申请的权限中有不同意授予的，如果有某个权限被永久拒绝就返回 true 给开发人员，让开发者引导用户去设置界面开启权限
        mCallBack.noPermission(
                deniedPermission, PermissionUtils.isPermissionPermanentDenied(ability, deniedPermission));

        // 证明还有一部分权限被成功授予，回调成功接口
        if (!grantedPermission.isEmpty()) {
            mCallBack.hasPermission(grantedPermission, false);
        }
    }

    /**
     * 应用权限详情回调
     *
     * @param reqAbility reqAbility
     * @param strings strings
     */
    public void onAbilityResult(Ability reqAbility, List<String> strings) {
        if (strings == null || strings.isEmpty()) {
            return;
        }
        if (reqAbility == null || reqAbility.isTerminating()) {
            return;
        }
        if (mCallBack == null) {
            return;
        }
        List<String> hasPermissions = new ArrayList<>();
        List<String> deniedPermissions = new ArrayList<>();
        for (String str : strings) {
            boolean isHas = PermissionUtils.isPermissionGranted(reqAbility, str);
            if (isHas) {
                hasPermissions.add(str);
            } else {
                deniedPermissions.add(str);
            }
        }
        if (strings.size() == hasPermissions.size()) {
            mCallBack.hasPermission(strings, true);
        } else {
            mCallBack.noPermission(deniedPermissions, false);
            if (!hasPermissions.isEmpty()) {
                mCallBack.hasPermission(hasPermissions, false);
            }
        }
    }
}
